package com.yeyks.wxcode.service;

import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.bean.order.WxPayAppOrderResult;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.google.common.collect.Maps;
import com.yeyks.util.OkHttpUtil;
import com.yeyks.wxcode.config.WxConfig;
import com.yeyks.wxcode.dto.WxPayParam;
import com.yeyks.wxcode.dto.WxRefundParam;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.Map;

/**
 * @Author fuchangshuai
 * @date 2019/4/12 3:08 PM
 */
@Slf4j
@Service
public class WxLoginService {
    @Autowired
    private WxConfig wxConfig;
    @Autowired
    private OkHttpClient okHttpClient;
    @Autowired
    private WxPayService payService;

    /**
     * 通过code和type(gzh或xcx,默认gzh)获取微信openId
     *
     * "access_token":"ACCESS_TOKEN",
     * "expires_in":7200,
     * "refresh_token":"REFRESH_TOKEN",
     * "openid":"OPENID",
     * "scope":"SCOPE"
     * @param code
     * @param type
     * @return
     */
    public String getOpenId(String code, String type) {
        try {
            String url = wxConfig.getOpenIdUrl(type, code);
            String response = OkHttpUtil.get(okHttpClient, url);
            JSONObject jsonObject = JSONObject.parseObject(response);
            return (String) jsonObject.get("openid");
        } catch (Exception e) {
            log.info("获取openId失败{}", e.getLocalizedMessage());
        }
        return null;
    }

    /**
     * 微信统一下单
     *
     * @param payParam
     * @return
     */
    public WxPayMpOrderResult unifiedOrder(WxPayParam payParam) {
        Map<String, String> map = wxConfig.getWxModel(payParam.getType());
        payService.getConfig().setAppId(map.get("appId"));
        //生成预支付订单
        WxPayUnifiedOrderRequest prepayInfo = WxPayUnifiedOrderRequest.newBuilder()
                .openid(payParam.getOpenId())
                .outTradeNo(payParam.getOrderNo())
                .totalFee(payParam.getTotalFee())
                .body(payParam.getBody())
                .tradeType(payParam.getTradeType())
                .spbillCreateIp(payParam.getCreateIp())
                .notifyUrl(payParam.getNotifyUrl())
                .build();
        WxPayMpOrderResult result = null;
        try {
            result = this.payService.createOrder(prepayInfo);
        } catch (WxPayException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 微信app支付
     *
     * @param payParam
     * @return
     */
    public WxPayAppOrderResult appPay(WxPayParam payParam) {
        Map<String, String> map = wxConfig.getWxModel(payParam.getType());
        payService.getConfig().setAppId(map.get("appId"));
        WxPayAppOrderResult result = null;
        try {
            //生成预支付订单
            WxPayUnifiedOrderRequest prepayInfo = WxPayUnifiedOrderRequest.newBuilder()
                    .outTradeNo(payParam.getOrderNo())
                    .totalFee(payParam.getTotalFee())
                    .body(payParam.getBody())
                    .tradeType(payParam.getTradeType())
                    .spbillCreateIp(payParam.getCreateIp())
                    .notifyUrl(payParam.getNotifyUrl())
                    .build();
            result = payService.createOrder(prepayInfo);
        } catch (Exception e) {
            log.error("微信支付失败！订单号：{},原因:{}", payParam.getOrderNo(), e.getMessage());
            e.printStackTrace();
        }
        return result;
    }


    /**
     * 订单退款
     *
     * @param wxRefundParam
     * @return WxPayRefundResult
     */
    public WxPayRefundResult refund(WxRefundParam wxRefundParam) {
        Map<String, String> map = wxConfig.getWxModel(wxRefundParam.getType());
        payService.getConfig().setAppId(map.get("appId"));
        WxPayRefundResult result = null;
        try {
            //生成预支付订单
            WxPayRefundRequest refundRequest = WxPayRefundRequest.newBuilder()
                    .outTradeNo(wxRefundParam.getOutTradeNo())
                    .outRefundNo(wxRefundParam.getOutRefundNo())
                    .totalFee(wxRefundParam.getTotalFee())
                    .refundFee(wxRefundParam.getRefundFee())
                    .build();
            result = payService.refund(refundRequest);
        } catch (Exception e) {
            log.error("微信支付失败！订单号：{},原因:{}", wxRefundParam.getOutTradeNo(), e.getMessage());
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 订单退款
     *
     * @param wxRefundParam
     * @return boolean
     */
    public Boolean disPoseRefund(WxRefundParam wxRefundParam) {
        try {
            WxPayRefundResult refund = refund(wxRefundParam);
            if (refund == null) {
                log.error("订单退款返回数据为空");
                return false;
            }
            if (refund.getResultCode().equals("SUCCESS")
                    && refund.getRefundFee().equals(wxRefundParam.getRefundFee())) {
                return true;
            } else {
                log.error("订单退款失败{}", JSONObject.toJSONString(refund));
                return false;
            }
        } catch (Exception e) {
            log.error("订单退款异常{}", e.getLocalizedMessage());
            return false;
        }
    }

    /**
     * 将返回的map格式修改一下
     *
     * @param payParam
     * @return
     */
    public Map<String, String> appDisposePay(WxPayParam payParam) {
        Map<String, String> result = Maps.newHashMap();
        try {
            WxPayAppOrderResult resultDTO = appPay(payParam);
            result.put("appid", resultDTO.getAppId());
            result.put("noncestr", resultDTO.getNonceStr());
            result.put("package", resultDTO.getPackageValue());
            result.put("partnerid", resultDTO.getPartnerId());
            result.put("prepayid", resultDTO.getPrepayId());
            result.put("timestamp", resultDTO.getTimeStamp());
            result.put("sign", resultDTO.getSign());
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
}
